package xfuzzy.alg_genetico.indeterminado.xfghlOld.model;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.management.ManagementFactory;
import java.lang.management.OperatingSystemMXBean;

import xfuzzy.alg_genetico.indeterminado.xfghlOld.model.spec.XfghlOperSet;
import xfuzzy.lang.Operatorset;
import xfuzzy.xfds.XfdsDataSet;
import xfuzzy.xfds.XfdsParser;

/**
 * 
 * @author Sergio Cala Cordero
 * 
 */

public class XfghlConfig {

	/**
	 * Fichero en el que se encuentra el conjunto de datos a utilizar
	 */
	private File datasetfile;
	
	/**
	 * Conjunto de datos a utilizar
	 */
	private XfdsDataSet dataset;
	
	
	/**
	 * Fichero de salida
	 */
	private String outPutFile;
	
	
	/**
	 * Estilo comun a todas las variables de entrada
	 */
	private int styleInPut;
	
	/**
	 * Numero de funciones de petenencia de la variable de entrada
	 */
	private int  mfs;
		
	/**
	 * El algoritmo de ajuste elegido
	 */
    private int algorithm;
	
	/**
	 * Parametro Initial Update del algoritmo
	 */
	private double iniUpd;

	/**
	 * Parametro Increase Factor del algoritmo
	 */	
	private double incFact;
	
	/**
	 * Parametro Decrease Factor del algoritmo
	 */
	private double decFact;
		
	/**
	 * Operador AND
	 */
    private int andOperator;
    
    /**
     * Operator Defuz
     */
    private int DefuzOperator;
	
	/**
	 * Numero de entradas de nuestro modulo
	 */
	private int numVarEnt;
	

	/**
	 * Nombre del sistema
	 */	
	private String nameSystem;
	
	/**
	 * Numero de iteraciones del algoritmo de ajuste
	 */
	private int numIterAjust;	
	
	
	/**
	 * Numero de thread
	 */
	private int numThread;	

	/**
	 * Variable que nos dice el numero de procesadores disponibles
	 */
	private int numProc;

	
	/**
	 * Numero de estructuras
	 */
	private int numChrom;	
	
    /**
     * Conjunto de operadores
     */
	private Operatorset operSet;
	
	/**
	 * Numero de generaciones del algoritmo genetico
	 */
	private int numGenerations;
	
	/**
	 * Probabilidad de mutacion
	 */
	private double probMut;
	
	/**
	 * Probabilidad de cruce
	 */
	private double probCross;


	
	/**
	 * Constructor por defecto 
	 */
	public XfghlConfig()
    {
		
    }
	
	
	/**
	 * 	
	 * @param nameSystem        Nombre que va a llevar el sistema final
	 * @param numIterAjus       Numero de iteraciones que va a utilizar el algoritmo
	 * @param numThread         Numero de hebras que va a utilizar el programa
	 * @param file              Archivo que contiene el data set
	 * @param iniUpd			Parametro Initial Update del algoritmo RPROP
	 * @param incFact			Parametro Increase Factor del algortimo RPROP
	 * @param decFact			Parametro Decrease Factor del algortimo RPROP
	 * @param andOperator       Operador AND
	 * @param defuzOperator     Operador de defuzificacion
	 * @param styleInPut        Estilo de las variables de entrada
	 * @param mfs               Numero de varibales de funciones de las variables de entrada
	 * @param alg				Algoritmo de ajuste elegido
	 * 
	 */
	
	public XfghlConfig(String nameSystem,int numIterAjus,int numThread,File file,double iniUpd,double incFact,double decFact,int andOperator,int defuzOperator,int styleInPut,int  mfs,int alg,int numChrom,int numGenerations,double probMut,double probCross)
	{
	  	setDataSet(file);	  
	  	
	  	this.nameSystem=nameSystem;
	  	this.numVarEnt=this.dataset.getNumberOfInputs();
	  	this.numIterAjust=numIterAjus;
	  	this.numThread=numThread;
	  	//this.numStruct=XfghlHierStruct.numEstructuras(this.numVarEnt);
	  	this.algorithm=alg;
	  	this.iniUpd=iniUpd;
	  	this.incFact=incFact;
	  	this.decFact=decFact;	  
	  	this.andOperator=andOperator;
	  	this.DefuzOperator=defuzOperator;
	  	this.operSet=XfghlOperSet.create("OperSet", andOperator, defuzOperator);
	  	this.styleInPut=styleInPut;
	  	this.mfs=mfs;
	  	this.numChrom=numChrom;
	  	this.numGenerations=numGenerations;
	  	this.probMut=probMut;
	  	this.probCross=probCross;
	  	
	  	
	  	OperatingSystemMXBean  mxbean;   
		mxbean= ManagementFactory.getOperatingSystemMXBean();							
	  	this.numProc=mxbean.getAvailableProcessors();
	  	
	}
	
	public boolean setDataSet(File file) {
		try {
			this.datasetfile = file;
			FileInputStream fis = new FileInputStream(datasetfile);
			XfdsParser parser = new XfdsParser(fis);
			XfdsDataSet ds = parser.parse();
			if(ds == null) return false;
			this.dataset = ds;					
			return true;
		}
		catch(Exception ex) {
			return false;
		}
	}
	
	/**
	 * Obtiene el fichero del conjunto de datos
	 * @return
	 */
	public File getDataSetFile() {
		return this.datasetfile;
	}
	
	public int getnumIterAjust()
	{
		return this.numIterAjust;
	}


	public int getNumThread()
	{
		if(this.numThread==-1)
			return this.numProc;
		else			
			return this.numThread;
	}
	
	public int getValueThread()
	{
		return this.numThread;
	}
	
	public void setNumThread(int numThread)
	{
		
		this.numThread=numThread;
	}
    
	
	public void setNameSystem(String name)
	{
		this.nameSystem=name;
	}
	
	public String getNameSystem()
	{
		return this.nameSystem;
	}
	
	public Operatorset getOperSet()
	{
		return this.operSet;
	}
	
	public XfdsDataSet getDataSet()
	{
		return this.dataset;
	}
	
	public int getStileInput()
	{
		return this.styleInPut;
	}
	
	public int getMfs()
	{
		return this.mfs;
	}
	
	
	public String getOutputFile()
	{
		return this.outPutFile;
	}
	
	public  double getIniUpd()
	{
		return this.iniUpd;
		
	}
	
	public double getIncFact()
	{
		return this.incFact;
	}
	
	public double getDecFact()
	{
		return this.decFact;
	}
		
	public int getAndOperator()
	{
		return this.andOperator;
	}
	
	public int getDefuzOperator()
	{
		return this.DefuzOperator;
	}
	
	public int getAlgorithm()
	{
		return this.algorithm;
	}
	
	public String toXML()
	{
		String eol = System.getProperty("line.separator", "\n");
		String code = "<xfuzzy>"+eol;
		code += "\t<xfhl system=\""+this.nameSystem+"\">"+eol;				
		
	    code+="\t\t<dataset file=\""+this.datasetfile.getAbsolutePath()+"\"></dataset>"+eol+eol;
	    
	    code+="\t\t<!-- NumThreads: "+eol+"\t\t\tdefault -> Number of available processors in the system. "+eol
		 +"\t\t\tNumber of processors --> "+eol;
	    String threads;
	    if(this.numThread==-1)
	    	threads="default";
	    else
	    	threads=""+this.numThread;
	    code+="\t\t<threads numbers=\""+threads+"\"></threads>"+eol+eol;
	    
	    code+="\t\t<!-- ALGORITHM: "+eol+"\t\t\t0: RProp "+eol
		 +"\t\t\t1: Mardquardt Levenberg --> "+eol;
	    
	    code+="\t\t<learning algorithm =\""+this.algorithm+"\"></learning>"+eol+eol;
	    
	    code+="\t\t<!-- STYLE: "+eol+"\t\t\t1: Free Triangles "+eol
	    							 +"\t\t\t2: Free Shouldered Triangles "+eol
	    							 +"\t\t\t3: Free Gaussians "+eol
	    							 +"\t\t\t4: Triangles Family "+eol
	    							 +"\t\t\t5: Shouldered-Triangular Family "+eol
	    							 +"\t\t\t6: B-Splines Family --> "+eol;	    							 	    
	    code+="\t\t<input_type style=\""+this.styleInPut+"\" num_funct=\""+this.mfs+"\"></input_type>"+eol+eol;
	    
	    code+="\t\t<alg_param ini=\""+this.iniUpd+"\" inc_fact=\""+this.incFact+"\" dec_fact=\""+this.decFact+"\"></alg_param>"+eol+eol;
	    
	    code+="\t\t<end_condition interations=\""+this.numIterAjust+"\"></end_condition>"+eol+eol;
	    
	    code+="\t\t<!-- AND: "+eol+"\t\t\t0: Function MIN "+eol+
		 "\t\t\t1: Function PROD "+eol+
		 "\t\t DEFUZ: "+eol+"\t\t\t0: Fuzzy Mean "+eol+
		 "\t\t\t1: Weigthed Fuzzy Mean -->"+eol;
		 
	    code+="\t\t<operartor_set and=\""+this.andOperator+"\" defuz=\""+this.DefuzOperator+"\"></operartor_set>"+eol+eol;
			     		
		code += "\t</xfhl>"+eol;
		code += "</xfuzzy>";
		
		return code;
	}	
	
	/**
	 * 
	 * @param file El archivo d�nde vamos a a�adir la configuraci�n
	 * @return
	 */
	public boolean save(File file) {
		String code = toXML();
		byte buf[] = code.getBytes();

		try {
			OutputStream stream = new FileOutputStream(file,true);
			stream.write(buf);
			stream.close();
		}
		catch (IOException e) { return false; }
		return true;
	}


	/**
	 * @param numElemGeneraci�n the numElemGeneraci�n to set
	 */
	public void setNumChrom(int numChrom) {
		this.numChrom = numChrom;
	}


	/**
	 * @return the numElemGeneraci�n
	 */
	public int getNumChrom() {
		return this.numChrom;
	}
	
	public int getNumVarEnt() {
		return numVarEnt;
	}


	public void setNumVarEnt(int numVarEnt) {
		this.numVarEnt = numVarEnt;
	}


	/**
	 * @param numGenerations the numGenerations to set
	 */
	public void setNumGenerations(int numGenerations) {
		this.numGenerations = numGenerations;
	}


	/**
	 * @return the numGenerations
	 */
	public int getNumGenerations() {
		return numGenerations;
	}

	public double getProbMut() {
		return probMut;
	}


	public void setProbMut(double probMut) {
		this.probMut = probMut;
	}


	public double getProbCross() {
		return probCross;
	}


	public void setProbCross(double probCross) {
		this.probCross = probCross;
	}

}

